package org.fox.beetl.ext.spring.utils;

import java.io.Serializable;

import org.springframework.context.ApplicationContext;

/**
 * Spring Bean序列化类<br>
 * 注意非单例Bean慎用,可能会丢失部分数据<br>
 * 使用注意事项：<br>
 * 1. 使用本类进行序列化的Bean需要实现ApplicationContextAware和BeanNameAware接口以获取自身所在的应用程序上下文和bean名称 <br>
 * 2.使用本类警讯序列化的Bean需要定义成一个公有的明确指定了beanName的Bean，不能为内部Bean或匿名Bean<br>
 * 3.需要在顶级ApplicationContext中部署ApplicationContextLifecycleEventListener<br>
 * 达到此三个条件可以在对应Bean类中声明方法：
 *
 * <pre>
 * private Object writeReplace() {
 * 	return new SpringBeanSerializable(applicationContext.getId(), beanName);
 * }
 * </pre>
 *
 * @author Chen Rui
 */
public class SpringBeanSerializable implements Serializable {
	private static final long serialVersionUID = 1L;
	/* ----- ----- ----- ----- 属性 ----- ----- ----- ----- */
	/**
	 * Bean所属applicationContextId
	 */
	private String applicationContextId = null;
	/**
	 * bean名称
	 */
	private String beanName = null;

	/**
	 * @param applicationContextId
	 * @param beanName
	 */
	public SpringBeanSerializable(String applicationContextId, String beanName) {
		this.applicationContextId = applicationContextId;
		this.beanName = beanName;
	}

	/* ----- ----- ----- ----- 反序列化对象替换方法 ----- ----- ----- ----- */
	/**
	 * 将序列化内容还原成原Spring Bean的方法
	 *
	 * @return
	 */
	private Object readResolve() {
		ApplicationContext applicationContext = ApplicationContextLifecycleEventListener
				.getApplicationContext(applicationContextId);

		if (applicationContext == null) {
			throw new IllegalStateException(String.format("id为%s的ApplicationContext不存在", applicationContextId));
		}

		return applicationContext.getBean(beanName);
	}
}
